/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package it.txt.access.capability.libraries.rabbitmq;

import it.txt.access.capability.libraries.rabbitmq.exception.AbstractApplicationException;
import it.txt.access.capability.libraries.rabbitmq.impl.model.AbstractApplicationModel;
import it.txt.access.capability.libraries.rabbitmq.settings.AbstractApplicationSettings;
import it.txt.access.capability.services.ens.schema.FailureResponseType;
import it.txt.access.capability.services.ens.schema.ResponseType;
import it.txt.access.capability.services.ens.schema.SuccessResponseType;
import java.io.IOException;
import java.util.Date;
import java.util.logging.Logger;
import javax.xml.datatype.XMLGregorianCalendar;

/**
 *
 * @author seccia
 */
public abstract class AbstractApplication {

    protected static final Logger LOGGER = Logger.getLogger(AbstractApplication.class.getName());
    protected AbstractApplicationModel applicationModel;
    protected CapabilityConnection capabilityConnection;

    public AbstractApplication(AbstractApplicationSettings settings) throws AbstractApplicationException {
        applicationModel = AbstractApplicationHelper.getAbstractRabbitMQAppModel(settings);
    }
    
    public final void connect() throws AbstractApplicationException {
        ////////////////////////////////////////////////////////////////////////
        GuestApplication guestRabbitMQApplication = new GuestApplication(applicationModel);
        ////////////////////////////////////////////////////////////////////////
        ResponseType responseType = guestRabbitMQApplication.newGuestTransaction();
        ////////////////////////////////////////////////////////////////////////
        if (responseType.isResult()) {
            ////////////////////////////////////////////////////////////////////
            SuccessResponseType success = responseType.getResultDetails().getSuccessResponse();            
            ////////////////////////////////////////////////////////////////////
            CapabilityConnectioProps connectionProps = new CapabilityConnectioProps();            
            connectionProps.setBrokerPort(success.getBrokerPort().intValue());
            connectionProps.setUsername(success.getSubject().getSubjectID());
            connectionProps.setSessionToken(success.getSessionToken());
            connectionProps.setBrokerVHost(success.getVirtualHost());
            connectionProps.setAccessToken(success.getAccessToken());
            connectionProps.setBrokerHost(success.getBrokerHost());
            connectionProps.setQueueName(success.getQueueName());
            ////////////////////////////////////////////////////////////////////
            XMLGregorianCalendar xmlgc = success.getSessionExpiration();
            Date expirationDate = xmlgc.toGregorianCalendar().getTime();
            connectionProps.setExpirationDate(expirationDate);
            ////////////////////////////////////////////////////////////////////
            this.capabilityConnection = new CapabilityConnection(connectionProps);
            ////////////////////////////////////////////////////////////////////
            try {
                this.capabilityConnection.newConnection();
            } catch (IOException e) {
                throw new AbstractApplicationException(e.getMessage(), e);
            }
            ////////////////////////////////////////////////////////////////////
        }
        else {
            FailureResponseType frt = responseType.getResultDetails().getFailureResponse();
            throw new AbstractApplicationException("Failure Response - "
                    + "See Details for more information", frt);
        }
    }
    
    public boolean isConnected() {
        if (capabilityConnection == null) {
            return false;
        } else {
            return capabilityConnection.isConnected();
        }
    }

    public void disconnect() throws AbstractApplicationException {
        if (capabilityConnection != null) {
            try {
                capabilityConnection.disconnect();
            } catch (IOException e) {
                throw new AbstractApplicationException(e.getMessage(), e);
            }
        }
    }
    
    protected CapabilityConnection getCapabilityConnection() throws AbstractApplicationException {
        if (capabilityConnection == null) {
            throw new AbstractApplicationException("Invalid State. The connect() method has not been called.");
        }
        return capabilityConnection;
    }

    public abstract void sessionRenegotiation() throws AbstractApplicationException;
}
